package com.wat.ext;

import com.wat.service.OrderService;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.beans.PropertyDescriptor;

/**
 * Bean级的方法是仅对该bean有效，容器级的方法是对所有bean有效。
 */
@Component(value = "testBeanLifecycle")
public class BeanLifecycle extends InstantiationAwareBeanPostProcessorAdapter implements
		BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, ApplicationContextAware,
		InitializingBean, DisposableBean  {

	private boolean printFlag = true;

	private int i = 1;
	private ApplicationContext applicationContext;
	private ClassLoader classLoader;
	private BeanFactory beanFactory;
	private String beanName;

	public BeanLifecycle() {
		print("【构造器-方法级】BeanLifecycle构造器执行了");
	}

	/**
	 * BeanNameAware 接口 【Aware-Bean级】
	 * 查看调用地方搜关键字：BeanNameAware#setBeanName()
	 * 在 AbstractAutowireCapableBeanFactory.invokeAwareMethods()方法调用
	 * 返回bean的名字，用处不大
 	 */
	@Override
	public void setBeanName(String name) {
		print("【Aware-Bean级】BeanNameAware 接口执行了,name:" + name);
		this.beanName = name;
	}

	/**
	 * BeanClassLoaderAware 接口 【Aware-Bean级】
	 * 查看调用地方搜关键字：BeanClassLoaderAware#setBeanClassLoader()
	 * 在 AbstractAutowireCapableBeanFactory.invokeAwareMethods()方法调用
	 *
	 */
	@Override
	public void setBeanClassLoader(ClassLoader classLoader) {
		print("【Aware-Bean级】BeanClassLoaderAware 接口执行了");
		this.classLoader = classLoader;
	}

	/**
	 * BeanFactoryAware 接口 【Aware-Bean级】
	 * 查看调用地方搜关键字：BeanFactoryAware#setBeanFactory()
	 * 在 AbstractAutowireCapableBeanFactory.invokeAwareMethods()方法调用
	 */
	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		print("【Aware-Bean级】BeanFactoryAware 接口执行了");
		this.beanFactory = beanFactory;
	}

	/**
	 * ApplicationContextAware 接口 【BeanPostProcessor-Bean级】
	 * 查看调用地方搜关键字：ApplicationContextAware#setApplicationContext()
	 * 在 AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization()方法调用
	 *
	 * 以下六个Aware都是通过 ApplicationContextAwareProcessor 处理器调用的
	 * 	EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware
	 * 	ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware
	 */
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		print("【ApplicationContextAwareProcessor-Bean级】ApplicationContextAware 接口执行了");
		this.applicationContext = applicationContext;
	}

	/**
	 * InitializingBean 接口 【InitializingBean-Bean级】
	 * 查看调用地方搜关键字：
	 * 在 AbstractAutowireCapableBeanFactory.invokeInitMethods()方法调用
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		print("【InitializingBean-Bean级】InitializingBean.afterPropertiesSet() 方法执行了");
	}

	/**
	 * 自定义 init-method 方法 【BeanPostProcessor-Bean级级】
	 * 查看调用地方搜关键字：AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization()
	 * 会包装成一个BeanPostProcessor，然后通过上面的方法调用
	 */
	@PostConstruct
	public void lifecycleInit() {
		print("【CommonAnnotationBeanPostProcessor-Bean级级】@PostConstruct init-method()  方法执行了");
	}


	/**
	 * InstantiationAwareBeanPostProcessorAdapter 接口
	 * 查看调用地方搜关键字：InstantiationAwareBeanPostProcessorAdapter#postProcessBeforeInstantiation
	 * 实例化前置处理器
	 * 在目标bean开始实例化前触发该方法。返回的bean对象可以是要使用的代理，而不是目标bean，从而有效地抑制了目标bean的默认实例化。
	 * 如果此方法返回非null对象，则bean创建过程将被短路（也就是正常bean实例化的后续流程不再执行）。
	 */
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		if (beanClass.getName().indexOf("OrderService") > 0) {
			print("【InstantiationAwareBeanPostProcessorAdapter-容器级】postProcessBeforeInstantiation() 实例化对象-开始");
		}
		return null;
	}

	/**
	 * InstantiationAwareBeanPostProcessorAdapter 接口
	 * 查看调用地方搜关键字：InstantiationAwareBeanPostProcessorAdapter#postProcessAfterInstantiation
	 * 实例化后置处理器
	 * 如果返回 false，代表不需要进行后续的属性设值，也不需要再经过其他的 BeanPostProcessor 的处理
	 */
	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		if (bean instanceof OrderService) {
			print("【InstantiationAwareBeanPostProcessorAdapter-容器级 postProcessAfterInstantiation() 实例化对象-结束");
		}
		return true;
	}

	/**
	 * InstantiationAwareBeanPostProcessorAdapter 接口
	 * 查看调用地方搜关键字：InstantiationAwareBeanPostProcessorAdapter#postProcessAfterInstantiation
	 * 实例化：接口方法、设置某个属性时调用
	 */
	@Override
	public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
			throws BeansException {
		if (bean instanceof OrderService){
			print("【InstantiationAwareBeanPostProcessorAdapter-容器级】postProcessPropertyValues() 实例化成员变量-开始");
		}
		return pvs;
	}

	/**
	 * BeanFactoryPostProcessor 接口
	 */
//	@Override
//	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
//		System.out.println(i++ + ".【BeanFactoryPostProcessor-容器级】BeanFactoryPostProcessor 接口执行了");
//	}

	/**
	 * InstantiationAwareBeanPostProcessorAdapter 接口
	 * 查看调用地方搜关键字：InstantiationAwareBeanPostProcessorAdapter#postProcessBeforeInitialization
	 * 接口
	 */
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (bean instanceof OrderService) {
			print("【InstantiationAwareBeanPostProcessorAdapter-容器级】postProcessBeforeInitialization() 初始化对象-开始,beanName:" + beanName);
		}
		return bean;
	}

	/**
	 * InstantiationAwareBeanPostProcessorAdapter 接口
	 * 查看调用地方搜关键字：InstantiationAwareBeanPostProcessorAdapter#postProcessAfterInitialization
	 * 接口
	 */
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean instanceof OrderService) {
			print("【InstantiationAwareBeanPostProcessorAdapter-容器级】postProcessAfterInitialization() 初始化对象-结束,beanName:" + beanName);
		}
		return bean;
	}

	/**
	 * 自定义 destroy-method 方法
	 */
	@PreDestroy
	public void lifecycleInitDestroy() {
		print("【@PreDestroy-方法级】 @PreDestroy destroy-method() 方法执行了");
	}


	/**
	 * DisposableBean 接口
	 */
	@Override
	public void destroy() throws Exception {
		print("【DisposableBean-Bean级】DisposableBean 接口执行了");
	}




	private void print(String data){
		if (printFlag){
			System.out.println(i++ + ". " + data);
		}
	}
}
